package com.blustc.detect.ane.androino;

import java.util.Vector;

import android.os.Handler;
import android.util.Log;

public class FSKDecoder extends Thread {

    private static int MINIMUM_BUFFER = 12;
    private static int MAXIMUM_BUFFER = MINIMUM_BUFFER * 10;

    private static final int CHECK_CODE = 0xa8;

    private static boolean forceStop;
    private Handler mClientHandler;
    private Vector<short[]> mSound;
    private static String TAG = "FSKDecoder";

    public FSKDecoder(Handler handler) {
        this.mClientHandler = handler;
        this.mSound = new Vector<short[]>();
        this.forceStop = false;
    }

    public void run() {
        while (!this.forceStop) {
            try {
                if (messageAvailable()) {
                    decodeSound();
                } else {
                    Thread.sleep(100);
                }
            } catch (InterruptedException e) {
                Log.e("FSKDecoder:run", "error", e);
                e.printStackTrace();
            }
        }
        Log.i(TAG, "STOP run()");

    }

    public synchronized void stopAndClean() {
        Log.i(TAG, "STOP stopAndClean()");
        this.forceStop = true;
    }

    private synchronized boolean messageAvailable() {
        boolean available = false;
        if (this.mSound.size() >= MINIMUM_BUFFER) available = true;
        return available;
    }


    public synchronized void addSound(short[] sound, int nBytes) {
        short[] data = new short[nBytes];
        for (int i = 0; i < nBytes; i++) {
            data[i] = sound[i];
        }
        this.mSound.add(data);
       // Log.v(TAG, "addSound nBytes=" + nBytes + " accumulated=" + this.mSound.size());

        if (this.mSound.size() > MAXIMUM_BUFFER) {
            Log.e(TAG, "ERROR addSound() buffer overflow size=" + this.mSound.size());
            // reset state and cleaning the buffer
            this.mSound.clear();
        }
    }

    private synchronized short[] consumeSoundMessage() {
        int counter = 0;
        for (int i = 0; i < MINIMUM_BUFFER; i++) {
            counter += this.mSound.elementAt(i).length;
        }
        short[] sound = new short[counter];
        counter = 0; // removing the first block (carrier)
        for (int i = 0; i < MINIMUM_BUFFER; i++) {
            short[] s = this.mSound.remove(0);
            for (int j = 0; j < s.length; j++) {
                sound[counter + j] = s[j];
            }
            counter += s.length;
        }
      //  Log.v(TAG, "FSKDEC:consumeSound() nBytes=" + sound.length);
       // Log.v(TAG, "FSKDEC:after consumeSound() mSound.=" + mSound.size());
        return sound;
    }


    private void decodeSound() {
        short[] sound = consumeSoundMessage();
       // Log.i(TAG, "decodeSound: length=" + sound.length);
        this.decodeFSK(sound);
    }

    private void decodeFSK(short[] audioData) {
        //Log.d(TAG, "decodeFSK: short length=" + audioData.length);
        try {
            byte[] messages = FSKModule.decodeSound(audioData);
            if (messages != null) {
                if ((messages[0] & 0xFF) == CHECK_CODE) {
                    this.mClientHandler.obtainMessage(ArduinoService.HANDLER_MESSAGE_FROM_ARDUINO, 0, 0, messages).sendToTarget();
                } else {
                    Log.i(TAG, "====decodeFSK():CHECK CODE ERROR====");
                    for (int i = 0; i < messages.length; i++) {
                        Log.i(TAG, "message[" + i + "]" + (messages[i] & 0xFF));
                    }
                    Log.i(TAG, "====================================");
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "decodeFSK():ERROR=" + e.getMessage(), e);
            this.mClientHandler.obtainMessage(ArduinoService.HANDLER_MESSAGE_FROM_ARDUINO, -2, 0).sendToTarget();
        }
    }

}
